/**
 * @Author: ls-mac
 * @Date:   2018-09-04T13:36:51+08:00
 * @Last modified by:   ls-mac
 * @Last modified time: 2019-11-05 16:55:23
 */

import React, { createElement } from 'react';
import { Spin } from 'antd';
import pathToRegexp from 'path-to-regexp';
import Loadable from 'react-loadable';
import { getMenuData } from './menu';

let routerDataCache;

const modelNotExisted = (app, model) =>
  // eslint-disable-next-line
  !app._models.some(({ namespace }) => {
    return namespace === model.substring(model.lastIndexOf('/') + 1);
  });

// wrapper of dynamic
const dynamicWrapper = (app, models, component) => {
  // register models
  models.forEach(model => {
    if (modelNotExisted(app, model)) {
      // eslint-disable-next-line
      app.model(require(`../models/${model}`).default);
    }
  });

  // () => require('module')
  // transformed by babel-plugin-dynamic-import-node-sync
  if (component.toString().indexOf('.then(') < 0) {
    return props => {
      if (!routerDataCache) {
        routerDataCache = getRouterData(app);
      }
      return createElement(component().default, {
        ...props,
        routerData: routerDataCache,
      });
    };
  }
  // () => import('module')
  return Loadable({
    loader: () => {
      if (!routerDataCache) {
        routerDataCache = getRouterData(app);
      }
      return component().then(raw => {
        const Component = raw.default || raw;
        return props =>
          createElement(Component, {
            ...props,
            routerData: routerDataCache,
          });
      });
    },
    loading: () => {
      return <Spin size="large" className="global-spin" />;
    },
  });
};

function getFlatMenuData(menus) {
  let keys = {};
  menus.forEach(item => {
    if (item.children) {
      keys[item.path] = {
        ...item,
      };
      keys = {
        ...keys,
        ...getFlatMenuData(item.children),
      };
    } else {
      keys[item.path] = {
        ...item,
      };
    }
  });
  return keys;
}

export const getRouterData = app => {
  const routerConfig = {
    '/': {
      component: dynamicWrapper(app, [], () => import('../layouts/BasicLayout')),
    },
    // 登录
    '/login': {
      component: dynamicWrapper(app, ['LoginM/login'], () => import('../routes/Login/Login')),
    },

    // 欢迎页
    '/welcome': {
      component: dynamicWrapper(app, [], () => import('../routes/Login/welcome')),
      name: 'welcome',
    },

    // 订单-列表
    '/Order/order-list': {
      component: dynamicWrapper(app, ['Order/orderList', 'Enterprise/packageList'], () =>
        import('../routes/Order/OrderList')
      ),
      name: '订单列表',
    },

    // 订单-后台下单
    '/Order/order-commit': {
      component: dynamicWrapper(app, ['Order/orderCommit', 'Enterprise/packageList'], () =>
        import('../routes/Order/OrderCommit')
      ),
      name: '后台下单',
    },

    // 订单-体检报告
    '/Order/order-report': {
      component: dynamicWrapper(app, ['Order/orderReport', 'Enterprise/packageList'], () =>
        import('../routes/Order/OrderReport')
      ),
      name: '体检报告',
    },
    // 订单-订单详情
    '/Order/order-detail': {
      component: dynamicWrapper(app, ['Order/orderDetail', 'Enterprise/packageList'], () =>
        import('../routes/Order/OrderDetail')
      ),
      name: '订单详情',
    },

    // 企业管理-企业列表
    '/Enterprise/list': {
      component: dynamicWrapper(app, ['Enterprise/enterpriseList'], () =>
        import('../routes/Enterprise/list')
      ),
      name: '企业列表',
    },
    // 企业管理-企业可体检门店
    '/Enterprise/company-storePage': {
      component: dynamicWrapper(app, ['Enterprise/companyStorePage'], () =>
        import('../routes/Enterprise/CompanyStorePage')
      ),
      name: '企业可体检门店',
    },
    // 企业管理-企业新增/修改
    '/Enterprise/company-storePage-add': {
      component: dynamicWrapper(
        app,
        ['Enterprise/companyStorePage', 'dict', 'Contract/contractList'],
        () => import('../routes/Enterprise/CompanyStorePageAdd')
      ),
      name: '企业新增/修改',
    },
    // 企业管理-员工列表
    '/Enterprise/employee-list': {
      component: dynamicWrapper(app, ['Enterprise/employeeList'], () =>
        import('../routes/Enterprise/EmployeeList')
      ),
      name: '员工列表',
    },
    // 企业管理-员工列表-新增
    '/Enterprise/employee-list-add': {
      component: dynamicWrapper(app, ['Enterprise/employeeList'], () =>
        import('../routes/Enterprise/EmployeeListAdd')
      ),
      name: '员工列表-新增',
    },

    // 企业管理-家属列表
    '/Enterprise/family-list': {
      component: dynamicWrapper(app, ['Enterprise/familyList'], () =>
        import('../routes/Enterprise/FamilyList')
      ),
      name: '家属列表',
    },
    // 企业管理-套餐列表
    '/Enterprise/package-list': {
      component: dynamicWrapper(app, ['Enterprise/packageList'], () =>
        import('../routes/Enterprise/PackageList')
      ),
      name: '套餐列表',
    },
    // 企业管理-套餐列表-新增
    '/Enterprise/package-list-add': {
      component: dynamicWrapper(app, ['Enterprise/packageList'], () =>
        import('../routes/Enterprise/PackageListAdd')
      ),
      name: '套餐列表-新增',
    },
    // 企业管理-套餐加项列表
    '/Enterprise/extraItem-list': {
      component: dynamicWrapper(app, ['Enterprise/extraItemList'], () =>
        import('../routes/Enterprise/ExtraItemList')
      ),
      name: '套餐加项列表',
    },
    // 企业管理-套餐加项列表新增/修改
    '/Enterprise/extraItem-list-add': {
      component: dynamicWrapper(app, ['Enterprise/extraItemList'], () =>
        import('../routes/Enterprise/ExtraItemListAdd')
      ),
      name: '套餐加项列表新增/修改',
    },

    // 企业管理-套餐服务
    '/Enterprise/service-list': {
      component: dynamicWrapper(app, ['Enterprise/extraItemList', 'Enterprise/serviceList'], () =>
        import('../routes/Enterprise/ServiceList')
      ),
      name: '套餐服务',
    },
    // 企业管理-套餐服务新增/修改
    '/Enterprise/service-list-add': {
      component: dynamicWrapper(app, ['Enterprise/extraItemList', 'Enterprise/serviceList'], () =>
        import('../routes/Enterprise/ServiceListAdd')
      ),
      name: '套餐加项列表新增/修改',
    },

    // 体检合同-合同列表
    '/Contract/contract-list': {
      component: dynamicWrapper(app, ['Contract/contractList'], () =>
        import('../routes/Contract/ContractList')
      ),
      name: '合同列表',
    },

    // 字典维护-省份列表
    '/Dict/province-list': {
      component: dynamicWrapper(app, ['Dict/provinceList'], () =>
        import('../routes/Dict/ProvinceList')
      ),
      name: '省份列表',
    },
    // 字典维护-城市列表
    '/Dict/city-list': {
      component: dynamicWrapper(app, ['Dict/cityList'], () => import('../routes/Dict/CityList')),
      name: '城市列表',
    },
    // 字典维护-体检机构
    '/Dict/institution-list': {
      component: dynamicWrapper(app, ['Dict/institutionList'], () =>
        import('../routes/Dict/InstitutionList')
      ),
      name: '体检机构',
    },

    // 字典维护-体检门店
    '/Dict/store-list': {
      component: dynamicWrapper(app, ['Dict/storeList'], () => import('../routes/Dict/StoreList')),
      name: '体检门店',
    },
    // 字典维护-门店特性
    '/Dict/store-features': {
      component: dynamicWrapper(app, ['Dict/storeFeatures'], () =>
        import('../routes/Dict/StoreFeatures')
      ),
      name: '门店特性',
    },
    // 字典维护-门店不可预约时间
    '/Dict/store-unavailableTimeList': {
      component: dynamicWrapper(app, ['Dict/storeUnavailableTimeList'], () =>
        import('../routes/Dict/StoreUnavailableTimeList')
      ),
      name: '门店不可预约时间',
    },

    // 字典维护-管理员维护
    '/System/admin-list': {
      component: dynamicWrapper(app, ['System/adminList'], () =>
        import('../routes/System/AdminList')
      ),
      name: '管理员维护',
    },
    // 字典维护-角色管理
    '/System/role-list': {
      component: dynamicWrapper(app, ['System/roleList'], () =>
        import('../routes/System/RoleList')
      ),
      name: '角色管理',
    },
    // 字典维护-节假日管理
    '/System/vocation-list': {
      component: dynamicWrapper(app, ['System/vocationList'], () =>
        import('../routes/System/VocationList')
      ),
      name: '节假日管理',
    },

    // end
    '/result/success': {
      component: dynamicWrapper(app, [], () => import('../routes/Result/Success')),
    },
    '/result/fail': {
      component: dynamicWrapper(app, [], () => import('../routes/Result/Error')),
    },
    '/exception/403': {
      component: dynamicWrapper(app, [], () => import('../routes/Exception/403')),
    },
    '/exception/404': {
      component: dynamicWrapper(app, [], () => import('../routes/Exception/404')),
    },
    '/exception/500': {
      component: dynamicWrapper(app, [], () => import('../routes/Exception/500')),
    },
  };
  // Get name from ./menu.js or just set it in the router data.
  const menuData = getFlatMenuData(getMenuData());

  // Route configuration data
  // eg. {name,authority ...routerConfig }
  const routerData = {};
  // The route matches the menu
  Object.keys(routerConfig).forEach(path => {
    // Regular match item name
    // eg.  router /user/:id === /user/chen
    const pathRegexp = pathToRegexp(path);
    const menuKey = Object.keys(menuData).find(key => {
      pathRegexp.test(`${key}`);
    });
    let menuItem = {};
    // If menuKey is not empty
    if (menuKey) {
      menuItem = menuData[menuKey];
    }
    let router = routerConfig[path];
    // If you need to configure complex parameter routing,
    // https://github.com/ant-design/ant-design-pro-site/blob/master/docs/router-and-nav.md#%E5%B8%A6%E5%8F%82%E6%95%B0%E7%9A%84%E8%B7%AF%E7%94%B1%E8%8F%9C%E5%8D%95
    // eg . /list/:type/user/info/:id
    router = {
      ...router,
      name: router.name || menuItem.name,
      authority: router.authority || menuItem.authority,
      hideInBreadcrumb: router.hideInBreadcrumb || menuItem.hideInBreadcrumb,
    };
    routerData[path] = router;
  });
  return routerData;
};
